package com.seezoon.domain.service.device;

import com.seezoon.domain.dao.mapper.UserDeviceFenceMapper;
import com.seezoon.domain.dao.mapper.UserDeviceMapper;
import com.seezoon.domain.dao.po.UserDeviceFencePO;
import com.seezoon.domain.dao.po.UserDevicePO;
import com.seezoon.domain.service.device.vo.FenceVO;
import com.seezoon.infrastructure.error.ErrorCode;
import com.seezoon.infrastructure.exception.Assertion;
import com.seezoon.infrastructure.exception.ExceptionFactory;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import java.time.Instant;
import java.util.List;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

/**
 * 设备围栏服务
 */
@Slf4j
@RequiredArgsConstructor
@Service
@Validated
public class DeviceFenceService {

    private final static int max = 10;
    private final UserDeviceFenceMapper userDeviceFenceMapper;
    private final UserDeviceMapper userDeviceMapper;

    /**
     * 创建围栏
     */
    @Transactional
    public int createFence(@Valid @NotNull FenceVO fenceVO) {
        List<UserDeviceFencePO> userDeviceFencePOS = userDeviceFenceMapper.selectByUidAndDeviceId(fenceVO.getUid(),
                fenceVO.getDeviceId());
        if (userDeviceFencePOS.size() > max) {
            throw ExceptionFactory.bizException(ErrorCode.DEVICE_FENCE_TO_MUCH);
        }
        // 检查设备是否在用户名下
        UserDevicePO userDevicePO = userDeviceMapper.selectByUidAndDeviceId(fenceVO.getUid(), fenceVO.getDeviceId());
        if (null == userDevicePO) {
            throw ExceptionFactory.bizException(ErrorCode.DEVICE_NOT_BIND);
        }

        UserDeviceFencePO fence = new UserDeviceFencePO();
        fence.setUid(fenceVO.getUid());
        fence.setDeviceId(fenceVO.getDeviceId());
        fence.setFenceName(fenceVO.getFenceName());
        fence.setCenterLatitude(fenceVO.getCenterLatitude());
        fence.setCenterLongitude(fenceVO.getCenterLongitude());
        fence.setRadius(fenceVO.getRadius());
        fence.setStatus(fenceVO.getStatus());
        fence.setCreateTime(Instant.now());
        fence.setUpdateTime(Instant.now());

        int affectedRows = userDeviceFenceMapper.insert(fence);
        Assertion.affectedOne(affectedRows);
        return affectedRows;
    }

    /**
     * 更新围栏
     */
    @Transactional
    public int updateFence(@Valid @NotNull FenceVO fenceVO) {
        UserDeviceFencePO existingFence = userDeviceFenceMapper.selectByPrimaryKey(fenceVO.getId());
        if (existingFence == null) {
            throw ExceptionFactory.bizException(ErrorCode.RECORD_NOT_EXISTS);
        }
        // 验证围栏是否属于该用户
        if (!Objects.equals(existingFence.getUid(), fenceVO.getUid())) {
            log.error("param illegal fence uid:{},but update by:{}", existingFence.getUid(), fenceVO.getUid());
            throw ExceptionFactory.bizException(ErrorCode.PARAM_ILLEGAL);
        }
        UserDeviceFencePO updateFence = new UserDeviceFencePO();
        updateFence.setId(fenceVO.getId());
        updateFence.setFenceName(fenceVO.getFenceName());
        updateFence.setCenterLatitude(fenceVO.getCenterLatitude());
        updateFence.setCenterLongitude(fenceVO.getCenterLongitude());
        updateFence.setRadius(fenceVO.getRadius());
        updateFence.setStatus(fenceVO.getStatus());
        updateFence.setUpdateTime(Instant.now());

        int affectedRows = userDeviceFenceMapper.updateByPrimaryKeySelective(updateFence);
        Assertion.affectedOne(affectedRows);
        return affectedRows;
    }

    /**
     * 删除围栏
     */
    @Transactional
    public int deleteFence(@NotNull Long id, @NotNull Long uid) {
        UserDeviceFencePO existingFence = userDeviceFenceMapper.selectByPrimaryKey(id);
        if (existingFence == null) {
            throw ExceptionFactory.bizException(ErrorCode.RECORD_NOT_EXISTS);
        }

        // 验证围栏是否属于该用户
        if (!Objects.equals(existingFence.getUid(), uid)) {
            log.error("param illegal fence uid:{},but delete by:{}", existingFence.getUid(), uid);
            throw ExceptionFactory.bizException(ErrorCode.PARAM_ILLEGAL);
        }

        int affectedRows = userDeviceFenceMapper.deleteByPrimaryKey(id);
        Assertion.affectedOne(affectedRows);
        log.info("Deleted fence: {} for user: {}", id, uid);
        return affectedRows;
    }
}